/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.sales.hancadpe.client.presenter.grid;

import br.com.sales.generics.client.presenter.events.EditRecordEvent;
import br.com.sales.generics.client.presenter.events.ShowLoadingEvent;
import br.com.sales.generics.client.request.HannaRequestCallback;
import br.com.sales.generics.client.utils.User;
import static br.com.sales.hancadpe.client.presenter.consts.HanCadPEConsts.CELL_EDITING;
import static br.com.sales.hancadpe.client.presenter.consts.HanCadPEConsts.CELL_REMOVING;
import static br.com.sales.hancadpe.client.presenter.consts.HanCadPEConsts.HEADER_ROW_INDEX;
import br.com.sales.hancadpe.client.service.HanCadPEService;
import br.com.sales.hancadpe.client.view.HanCadPEResources;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.web.bindery.event.shared.EventBus;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 *
 * @author v
 */
public class HanCadPEGrid extends FlexTable {

    private boolean isEditing = false;
    private int rowEditing;
    private JSONObject record;
    private final Map<Object, String> listRecords = new LinkedHashMap<>();
    private final HanCadPEService service;
    private final EventBus eventBus;
    private final Provider<User> user;

    @Inject
    public HanCadPEGrid(EventBus eventBus, HanCadPEService service, Provider<User> user) {
        this.user = user;
        this.service = service;
        this.eventBus = eventBus;
        createGrid();
    }

    @Override
    protected void onAttach() {
        super.onAttach();
        clear(20);
    }

    public final void createGrid() {
        this.insertRow(HEADER_ROW_INDEX);
        this.getRowFormatter().addStyleName(HEADER_ROW_INDEX, "flextable-header");

        addColumn("Cód.");
        addColumn("Dt. Registro");
        addColumn("Nome");
        addColumn("Nasc.");
        addColumn("Celular");
        addColumn("Usuário");
        addColumn("Tipo");
        addColumn("Editar");
        if (user.get().isManager()) {
            addColumn("Excluir");
        }
        this.setCellSpacing(0);
        this.addStyleName("flexttable-person");
        this.getColumnFormatter().setWidth(2, "40%");
        this.addTableListener(new TableListener() {
            @Override
            public void onCellClicked(SourcesTableEvents sender,
                    int row, int cell) {
                if (row > 0) {
                    switch (cell) {
                        case CELL_EDITING: {
                            record = new JSONObject(JsonUtils.safeEval(
                                    listRecords.get(Double.parseDouble(HanCadPEGrid.this.getText(row, 0)))));
                            eventBus.fireEvent(new EditRecordEvent(record));
                            isEditing = true;
                            rowEditing = row;
                            break;
                        }
                        case CELL_REMOVING: {
                            if (Window.confirm(
                                    "Deseja excluir (" + HanCadPEGrid.this.getText(row, 2) + ")?")) {
                                service.inactivate(Long.parseLong(HanCadPEGrid.this.getText(row, 0)), null);
                                removeRow(row);
                            }
                            break;
                        }
                    }
                }
            }
        });
    }
    
    public void setIsEditing(boolean isEditing) {
        this.isEditing = isEditing;
        if (!isEditing) {
            rowEditing = 0;
        }
    }

    public void refresh(Map parameters) {
        eventBus.fireEvent(new ShowLoadingEvent(true));
        service.refreshPerson(parameters, new HannaRequestCallback() {

            @Override
            public void onResponseReceived(Request request, Response response) {
                clear();
                isEditing = false;
                record = new JSONObject(JsonUtils.safeEval(response.getText()));
                addValueTogrid();
                eventBus.fireEvent(new ShowLoadingEvent(false));
            }
        });
    }

    @Override
    public void clear() {
        int rouCount = getRowCount();
        for (int i = rouCount - 1; i > 0; i--) {
            removeRow(i);
        }
    }

    private void clear(int start) {
        int rouCount = getRowCount();
        for (int i = rouCount - 1; i > 0; i--) {
            if (start >= i) {
                break;
            }
            removeRow(i);
        }
    }

    private void addValueTogrid() {
        int column = 0;
        int index = getRowCount();
        for (String item : record.keySet()) {
            listRecords.put(record.get(item).isObject().get("SEQ").isNumber().doubleValue(),
                    record.get(item).isObject().toString());

            addRow(convert(record.get(item).isObject().get("SEQ")), index, column++);
            addRow(convert(record.get(item).isObject().get("DT_REGISTRO")), index, column++);
            addRow(convert(record.get(item).isObject().get("NM_PESSOA_FISICA")), index, column++);
            addRow(convert(record.get(item).isObject().get("DT_NASCIMENTO")), index, column++);
            addRow(addMask(convert(record.get(item).isObject().get("NR_CELULAR")).toString()), index, column++);
            addRow(convert(record.get(item).isObject().get("NM_USUARIO")), index, column++);
            addRow(PersonType.getDescBytType(convert(record.get(item).isObject().get("IE_TIPO_USUARIO"))), index, column++);
            addRow(new Image(HanCadPEResources.INSTANCE.edit()), index, column++);
            if (user.get().isManager()) {
                addRow(new Image(HanCadPEResources.INSTANCE.cancel()), index, column++);
            }
            column = 0;
            index++;
        }
    }

    private String addMask(String value) {
        if (value == null || "".equals(value)) {
            return "";
        }
        StringBuilder valueFormated = new StringBuilder();
        valueFormated.append("(").append(value.substring(0, 2)).append(")");
        valueFormated.append(" ").append(value.substring(2, 6)).append("-");
        valueFormated.append(value.substring(6, value.length()));

        return valueFormated.toString();
    }

    public void addValueTogrid(JSONObject record) {
        int column = 0;
        int index = isEditing ? rowEditing : getRowCount();
        listRecords.put(record.get("SEQ").isNumber().doubleValue(),
                record.toString());

        addRow(convert(record.get("SEQ")), index, column++);
        addRow(convert(record.get("DT_REGISTRO")), index, column++);
        addRow(convert(record.get("NM_PESSOA_FISICA")), index, column++);
        addRow(convert(record.get("DT_NASCIMENTO")), index, column++);
        addRow(addMask(convert(record.get("NR_CELULAR")).toString()), index, column++);
        addRow(convert(record.get("NM_USUARIO")), index, column++);
        addRow(PersonType.getDescBytType(convert(record.get("IE_TIPO_USUARIO"))), index, column++);
        addRow(new Image(HanCadPEResources.INSTANCE.edit()), index, column++);
        if (user.get().isManager()) {
            addRow(new Image(HanCadPEResources.INSTANCE.cancel()), index, column++);
        }
        setIsEditing(false);
    }

    public boolean isEditing() {
        return isEditing;
    }

    private Object convert(JSONValue value) {
        if (value == null) {
            return "";
        }
        if (value instanceof JSONString) {
            return value.isString().stringValue();
        } else if (value instanceof JSONNumber) {
            return value.isNumber().toString();
        }
        return "";
    }

    private void addRow(Object value, int row, int cell) {
        if (isEditing) {
            Widget widget = createCellWidget(value);
            setWidget(rowEditing, cell, widget);
            getCellFormatter().addStyleName(rowEditing, cell, "flextable-cell");
        } else {
            Widget widget = createCellWidget(value);
            setWidget(row, cell, widget);
            getCellFormatter().addStyleName(row, cell, "flextable-cell");
        }
    }

    private Widget createCellWidget(Object cellObject) {
        Widget widget;

        if (cellObject instanceof Widget) {
            widget = (Widget) cellObject;
        } else {
            widget = new Label(cellObject.toString());
        }
        return widget;
    }

    private void addColumn(Object columnHeading) {
        Widget widget = createCellWidget(columnHeading);
        int cell = getCellCount(HEADER_ROW_INDEX);

        widget.addStyleName("flextable-column-label");

        setWidget(HEADER_ROW_INDEX, cell, widget);

        getCellFormatter().addStyleName(HEADER_ROW_INDEX, cell, "flextable-column-label-cell");
    }

    public enum PersonType {

        GERENTE("Gerente", "1"),
        CLIENTE("Cliente", "2"),
        FORNECEDOR("Fornecedor", "3"),
        ATENDENTE("Atendente", "4");

        private final String desc;
        private final String type;

        private PersonType(String desc, String type) {
            this.desc = desc;
            this.type = type;
        }

        public String getDesc() {
            return desc;
        }

        public String getType() {
            return type;
        }

        public static String getDescBytType(Object type) {
            if (type == null) {
                return "";
            }
            for (PersonType personType : values()) {
                if (personType.getType().equals(type)) {
                    return personType.getDesc();
                }
            }
            return null;
        }
    }  
}
